//Lindsay Ergenekan
//ergenekl@onid.oregonstate.edu
//CS311 - 400
//Homework 5 - Pipeline

#include "hw5.h"

int
main(int argc, char *argv[])
{

    char c;

    int pfd[2];  
    int pfd2[2];
    int pfd3[2];
    int pfd4[2];

//    const char * cat = "cat";
    const char * rev = "rev";
    const char * wc = "wc";
    const char * sort = "sort";
    const char * uniq = "uniq";
    const char * tee = "tee";                   /* Pipe file descriptors */
    char * file_name;
    char * output1_name; 
   char * output2_name;


    while ((c = getopt(argc, argv, "f:")) != -1)
    switch (c){ 
    case 'f':

//          file_name = argv[4];
 //           printf("file name : %s \n", file_name);
            output1_name = argv[2];
 //           printf("output1 name: %s \n", output1_name);
 //           output2_name = argv[6];
 //           printf("output2 name: %s \n", output2_name);
 

}

    if (pipe(pfd) == -1)                            /* Create pipe */
        printf("pipe 1 error");

    if (pipe (pfd2) == -1)
        printf("pipe 2 error");

    if (pipe(pfd3) == -1)                            /* Create pipe */
        printf("pipe 3 error");

    if (pipe(pfd4) == -1)                            /* Create pipe */
        printf("pipe 3 error");


//////////////////////////////////////////////////////////////////////////////Fork 1
    switch (fork()) {
    case -1:
       printf("fork 1 issue");

    case 0:             /* First child: exec 'ls' to write to pipe */
        if (close(pfd[0]) == -1)                    /* Read end is unused */
            printf("error closing pipe1");

        /* Duplicate stdout on write end of pipe; close duplicated descriptor */

        if (pfd[1] != STDOUT_FILENO) {              /* Defensive check */
            if (dup2(pfd[1], STDOUT_FILENO) == -1)
                perror("error opening dup2 - no. 1");
            if (close(pfd[1]) == -1)
                perror("error closing dup2 - no.1");
        }
 //       printf("In the rev function");
        execlp(rev, rev, (char *) NULL);          /* Writes to pipe */
        printf("execlp 1 error");

    default:            /* Parent falls through to create next child */
        break;
    }

    /* Parent closes unused file descriptors for pipe, and waits for children */

//////////////////////////////////////////////////////////////////////////////////////////////// Fork 2
    switch (fork()) {
    case -1:
        printf("-1 exit error - fork issue");

    case 0:             /* Second child: exec 'wc' to read from pipe */
        if (close(pfd[1]) == -1)                    /* Write end is unused */
          printf("issues closing pipe 1 in switch 2");

        if (close(pfd2[0]) == -1)                    /* Write end is unused */
          printf("issues closing pipe 1 in switch 2");

        /* Duplicate stdin on read end of pipe; close duplicated descriptor */

        //read in from pipe 1
            if (pfd[0] != STDIN_FILENO){ //"defensive check"... they may fool us by already being correct
                if(dup2(pfd[0], STDIN_FILENO) == -1){
                    perror ("Duplicate pfd failed");
                }
                if (close(pfd[0]) == -1){
                    perror("closing of duplicate descriptor failed");
                }
            }
        //write out on pipe 2 (do not do this if this is the last step (leave for STDOUT to print to screen))
            if (pfd2[1] != STDOUT_FILENO){ //"defensive check"... they may fool us by already being correct
                if(dup2(pfd2[1], STDOUT_FILENO) == -1){
                    perror ("Duplicate pfd failed");
                }
                if (close(pfd2[1]) == -1){
                    perror("closing of duplicate descriptor failed");
                }
    
            }
    
 //       printf("In the sort function");
        execlp(sort, sort, (char *) NULL);
        printf("execlp");

    default: /* Parent falls through */
        break;
    }

////////////////////////////////////////////////////////////////////////////// Fork 3
    switch (fork()) {
    case -1:
        printf("-1 exit error - fork issue");

    case 0:             /* Second child: exec 'wc' to read from pipe */
/////////////////////////////PIPE 1
        if (close(pfd[0]) == -1)                    /* Write end is unused */
          printf("issues closing pipe");
        if (close(pfd[1]) == -1)                    /* Write end is unused */
            printf("issues closing pipe");
///////////////////PIPE 2
        if (close(pfd2[1]) == -1)                    /* read end is unused */
            printf("issues closing pipe 2 read");
///////////////////////PIPE 3
       if (close(pfd3[0]) == -1)                    /* Write end is unused */
            printf("issues closing pipe 3 write");



        if (pfd2[0] != STDIN_FILENO){ //"defensive check"
                if(dup2(pfd2[0], STDIN_FILENO) == -1){
                    perror ("Duplicate pfd 2 dup failed");
                }
                if (close(pfd2[0]) == -1){
                    perror("closing of duplicate descriptor failed");
                }
    
            }
        
        if (pfd3[1] != STDOUT_FILENO){ //"defensive check".
                if(dup2(pfd3[1], STDOUT_FILENO) == -1){
                    perror ("Duplicate pfd failed");
                }
                if (close(pfd3[1]) == -1){
                    perror("closing of duplicate descriptor failed");
                }
    
            }
  //      printf("in the unique function");
        execlp(uniq, uniq, "-c", (char *) NULL);
        printf("execlp");

    default: /* Parent falls through */
        break;
    }

/////////////////////////////////////4th PIPE
   switch (fork()) {
    case -1:
        printf("-1 exit error - fork issue");

    case 0:             /* Second child: exec 'wc' to read from pipe */
////////////PIPE 1
        if (close(pfd[1]) == -1)                    /* read end is unused 1*/
          printf("issues closing pipe");
        if (close(pfd[0]) == -1)                    /* Write end is unused */
            printf("issues closing pipe");
////////PIPE 2
        if (close(pfd2[1]) == -1)                    /* read end is unused 2*/
          printf("issues closing pipe");
        if (close(pfd2[0]) == -1)                    /* Write end is unused 2*/
            printf("issues closing pipe");
////////////PIPE 3
        if (close(pfd3[1]) == -1)                    /* Wrea end is unused 3*/
            printf("issues closing pipe 2 read");
////////////PIPE 4
       if (close(pfd4[0]) == -1)                    /* Write end is unused 4*/
            printf("issues closing pipe 3 write");
        /* Duplicate stdin on read end of pipe; close duplicated descriptor */



        if (pfd3[0] != STDIN_FILENO) {               /* Defensive check */
            if (dup2(pfd3[0], STDIN_FILENO) == -1)
                printf("error dup2");
            if (close(pfd3[0]) == -1)
                printf("error closing");
        }


        if (pfd4[1] != STDOUT_FILENO) {               /* Defensive check */
            if (dup2(pfd4[1], STDOUT_FILENO) == -1)
                printf("error dup2");
            if (close(pfd4[1]) == -1)
                printf("error closing");
        }
//        printf("in the tee function");
        execlp(tee, tee, output1_name, (char *) NULL);
        printf("execlp");

    default: /* Parent falls through */
        break;
    }

///////////////////////////////////////////////////CASE 5
    switch(fork()){
        case -1:
            printf("Fork failed");
        
        case 0:
        
/////////////PIPE 1
         if(close(pfd[0]) == -1){
                perror("Close of pipe failed");
            }
         if(close(pfd[1]) == -1){
                perror("Close of pipe failed");
            }
        
//////////////PIPE 2
         if(close(pfd2[0]) == -1){
                perror("Close of pipe failed");
            }
         if(close(pfd2[1]) == -1){
                perror("Close of pipe failed");
            }
        

/////////PIPE 3
         if(close(pfd3[0]) == -1){
                perror("Close of pipe failed");
            } 
         if(close(pfd3[1]) == -1){
                perror("Close of pipe failed");
            }   
        
////////////////////PIPE 4              
         if(close(pfd4[1]) == -1){
                perror("Close of pipe failed");
            }       
 

        //read in from pfd3
            if (pfd4[0] != STDIN_FILENO){ //"defensive check"... they may fool us by already being correct
                if(dup2(pfd4[0], STDIN_FILENO) == -1){
                    perror ("Duplicate pfd failed");
                }
                if (close(pfd4[0]) == -1){
                    perror("closing of duplicate descriptor failed");
                }
    
            }


 //       printf("in the wc function");
        execlp(wc, wc, (char *) NULL); 
        printf("not supposed to be here");    

    default: //parent does nothing here but continue on    
            break;    
    } 

    
    if (close(pfd[0]) == -1)
       printf("close 5");
    if (close(pfd[1]) == -1)
        printf("close 6");

    if (close(pfd2[0]) == -1)
       printf("close 5");
    if (close(pfd2[1]) == -1)
        printf("close 6");

    if (close(pfd3[0]) == -1)
       printf("close 5");
    if (close(pfd3[1]) == -1)
        printf("close 6");

    if (close(pfd4[0]) == -1)
       printf("close 5");
    if (close(pfd4[1]) == -1)
        printf("close 6");

    if (wait(NULL) == -1)
        printf("wait 1");
    if (wait(NULL) == -1)
        printf("wait 2");
    if (wait(NULL) == -1)
        printf("wait 3");
    if (wait(NULL) == -1)
        printf("wait 4");

    exit(EXIT_SUCCESS);
}